package com.iflytek.read.util;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.iflytek.read.Constant;
import com.iflytek.read.bean.FloatWindowBean;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * @author wangshuai
 */
@SuppressWarnings("ALL")
public class DownloaderUtil {

    private static final String TAG = "DownloaderUtil";
    private static final ExecutorService executorService = ThreadPoolUtils.newSingleThreadExecutor("my-single-pool");

    private static volatile Future<?> currentTask;
    private static volatile boolean isCancelled = false;
    private static volatile boolean isDownloading = false;
    private static volatile String currentSliceId = null;

    public interface DownloadListener {

        /**
         * 下载成功
         * @param bean  播放信息
         * @param file  下载的文件
         */
        void onDownloadSuccess(FloatWindowBean bean, File file);

        /**
         * 下载失败
         * @param e 失败信息
         */
        void onDownloadFailed(Exception e);

        /**
         * 下载进度
         * @param progress  进度值
         */
        void onProgressUpdate(int progress);

        /**
         * 取消下载
         */
        void onDownloadCancelled();
    }

    /**
     * 检查是否正在下载中
     * @return 是否正在下载
     */
    public static boolean isDownloading() {
        return isDownloading;
    }

    /**
     * 获取当前正在下载的sliceId
     * @return 当前sliceId
     */
    public static String getCurrentSliceId() {
        return currentSliceId;
    }

    public static void downloadWavFile(Context context, FloatWindowBean bean,
                                       String fileUrl, String fileName,
                                       DownloadListener listener) {

        String newSliceId = bean.getSliceId();

        // 如果正在下载，先取消当前下载
        if (isDownloading) {
            LogUtil.d(TAG, "Cancelling current download with sliceId: " + currentSliceId +
                    ", starting new download with sliceId: " + newSliceId);
            cancelDownload();
        } else {
            LogUtil.d(TAG, "Starting new download with sliceId: " + newSliceId);
        }

        // 重置取消状态
        isCancelled = false;
        isDownloading = true;
        currentSliceId = newSliceId;

        // 处理文件名
        final String finalFileName = fileName.toLowerCase().endsWith(Constant.TYPE_WAV)
                ? fileName
                : fileName + ".wav";

        Handler handler = new Handler(Looper.getMainLooper());

        // 提交任务并保存Future引用
        currentTask = executorService.submit(() -> {
            try {
                OkHttpClient client = getUnsafeOkHttpClient();
                Request request = new Request.Builder()
                        .url(fileUrl)
                        .build();

                try (Response response = client.newCall(request).execute()) {
                    if (!response.isSuccessful()) {
                        throw new IOException("Unexpected code " + response);
                    }

                    ResponseBody body = response.body();
                    if (body == null) {
                        throw new IOException("Response body is null");
                    }

                    long fileLength = body.contentLength();
                    InputStream inputStream = body.byteStream();

                    File directory = context.getFilesDir();
                    File outputFile = new File(directory, finalFileName);

                    if (outputFile.exists() && !outputFile.delete()) {
                        throw new IOException("Could not delete existing file");
                    }

                    OutputStream outputStream = new FileOutputStream(outputFile);
                    byte[] buffer = new byte[4096];
                    long total = 0;
                    int count;
                    int lastProgress = 0;

                    while ((count = inputStream.read(buffer)) != -1) {
                        // 检查是否已取消
                        if (isCancelled) {
                            handler.post(() -> {
                                if (listener != null) {
                                    listener.onDownloadCancelled();
                                }
                            });
                            // 关闭流和删除部分下载的文件
                            outputStream.close();
                            inputStream.close();
                            if (outputFile.exists()) {
                                outputFile.delete();
                            }
                            isDownloading = false;
                            currentSliceId = null;
                            return;
                        }

                        outputStream.write(buffer, 0, count);
                        total += count;

                        if (fileLength > 0) {
                            int progress = (int) (total * 100 / fileLength);
                            if (progress > lastProgress) {
                                handler.post(() -> {
                                    if (listener != null) {
                                        listener.onProgressUpdate(progress);
                                    }
                                });
                                lastProgress = progress;
                            }
                        }
                    }

                    outputStream.flush();
                    outputStream.close();
                    inputStream.close();

                    handler.post(() -> {
                        if (listener != null) {
                            listener.onDownloadSuccess(bean, outputFile);
                        }
                    });
                    isDownloading = false;
                    currentSliceId = null;
                }
            } catch (Exception e) {
                isDownloading = false;
                currentSliceId = null;
                if (!isCancelled) { // 只有不是主动取消的情况才报告错误
                    LogUtil.e(TAG, "Download failed for sliceId: " + newSliceId, e);
                    handler.post(() -> {
                        if (listener != null) {
                            listener.onDownloadFailed(e);
                        }
                    });
                }
            }
        });
    }

    /**
     * 取消当前下载任务
     */
    public static void cancelDownload() {
        LogUtil.d(TAG, "Cancelling download with sliceId: " + currentSliceId);
        isCancelled = true;
        isDownloading = false;
        if (currentTask != null) {
            currentTask.cancel(true);
            currentTask = null;
        }
        currentSliceId = null;
    }

    /**
     * 创建一个不验证证书的 TrustManager
     */
    public static OkHttpClient getUnsafeOkHttpClient() {
        try {
            @SuppressLint("CustomX509TrustManager")
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {}

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {}

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder()
                    .connectTimeout(15, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .callTimeout(60, TimeUnit.SECONDS);
            builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
            builder.hostnameVerifier((hostname, session) -> true);

            return builder.build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 关闭线程池
     */
    public static void shutdown() {
        executorService.shutdown();
    }
}